#ifndef __PX_PAD_LOG_POLLER_H__
#define __PX_PAD_LOG_POLLER_H__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <atomic>
#include <thread>
#include <functional>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <assert.h>
#include <sys/stat.h>
#include "PadTypeConv.h"
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
#include  <io.h>
#else
#include <sys/syscall.h>
#endif
#include <map>

namespace PadLog
{
constexpr int32_t ThrdCnt = 32;                       //默认线程写入数量

class CLog;
struct CLogPack;
typedef std::function<void(CLogPack*)> _DumpFile;
typedef std::function<CLog*(int32_t)> _GetLog;

#define IncId(_id) \
    int32_t _id1 = _id.fetch_add(1)

//日志记录的前缀头
struct CLogPack
{
    int16_t logid = 0;
    int16_t lv = 0;
    int16_t arg_num = 0;        //参数个数
    int16_t num = 0;            //format格式句长度
    int32_t tid = 0;
    int32_t length = 0;         //参数总长: 类型 参长 数据
    int64_t nanos = 0;
    const char* format_ptr = NULL;
public:
    CLogPack() {}
    CLogPack(int16_t id, int16_t _lv, int32_t _tid, int64_t _nanos, int16_t _arg_num, const char* ptr, int16_t arr_size, int32_t len)
        : logid(id), lv(_lv), arg_num(_arg_num), num(arr_size), tid(_tid), length(len), nanos(_nanos), format_ptr(ptr)
    {}
};

constexpr int32_t LogPackSize = sizeof(CLogPack);

const char* const LvArr[] = {"[ALL]", "[DEBUG]", "[INFO]", "[WARN]", "[ERROR]", "[MARK]"};

constexpr int32_t NoDateLogNum = 20;              //如果是滚动的 限制最多20个文件

inline int64_t nanos()
{
#ifndef _WIN32
    auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
#else
    auto duration = std::chrono::system_clock::now().time_since_epoch();
#endif
    auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
    return nanos.count();
}

class CLog
{
public:
    //!
    int64_t m_file_size = 0;
    int64_t m_rd_fize = 0;
    //!
    FILE* m_fp = NULL;
    //!
    int32_t m_is_date = 0;
    int32_t m_log_num = 0;
    int32_t m_log_limit = 0;
    int32_t m_rotate = 0;
    uint32_t m_cnt = 0;
    //!
    int32_t m_lv = 0;
    //!
    uint32_t m_pid = 0;
    //!
    std::string m_file_prefix;
    std::string m_file_name;
public:
    int32_t init(const char* fileName, const char* path, int32_t lv, int32_t fileSize, int32_t fileNum, int32_t date, int32_t rotate)
    {
        static std::atomic<int32_t> m_id = {0};
        m_file_size = fileSize;
        m_is_date = date;
        m_log_limit = fileNum;
        m_log_num = fileNum;
        m_rotate = rotate;
        m_lv = lv;
#ifdef _WIN32
        m_pid = GetCurrentProcessId();
#else
        m_pid = getpid();
#endif
        if (path && path[0])
        {
            int p_size = strlen(path);
            char* path_ = new char[p_size + 1];
            memset(path_, 0, p_size + 1);
            int p = 0;
            for (int i = 0; i <= p_size; ++i)
            {
                if (path[i] == '/' || path[i] == '\\' || i == p_size)
                {
                    memcpy(path_, path, i);
                    if (i == 0)
                    {
                        continue;
                    }
                    path_[i] = '\0';
                }
                else
                {
                    continue;
                }
#ifndef _WIN32
                if (-1 == access(path_, 0))
                {
                    if (0 != mkdir(path_, 0755))
                    {
                        printf("[ERROR] InitLogger create log dir: [%s] error: %d\n", path_, errno);
                        delete[] path_;
                        return -1;
                    }
                }
#else
                if (-1 == _access(path_, 0))
                {
                    if (0 != _mkdir(path_))
                    {
                        printf("[ERROR] InitLogger create log dir: [%s] error: %d\n", path_, errno);
                        delete[] path_;
                        return -1;
                    }
                }
#endif
            }
            delete[] path_;
            m_file_prefix += std::string(path) + "/";
            m_file_prefix += std::string(fileName);
        }
        else
        {
            m_file_prefix = fileName;
        }
        m_file_name = m_file_prefix;
        if (m_is_date == 1)
        {
            char timeString[0x40] = {0};
            time_t unixTime = std::time(NULL);
            std::tm* tm = localtime(&unixTime);
            strftime(timeString, sizeof(timeString), "_%Y%m%d_%H%M%S.log", tm);
            m_file_name += timeString;
        }
        else if (m_is_date == 2)
        {
            m_file_name += ".log";
            struct stat buf;
            if (stat(m_file_name.c_str(), &buf) == 0)
            {
                uint64_t file_size = (uint64_t)buf.st_size;
                m_rd_fize = file_size;
            }
        }
        else
        {
            m_file_name += ".log";
            //查填充哪个日志文件
            for (; m_log_num < m_log_limit; ++m_log_num)
            {
                if (m_log_num > 0)
                {
                    m_file_name = m_file_prefix;
                    char name[16] = { 0 };
                    name[0] = '_';
                    int len = sprintf(name + 1, "%d", m_log_num);
                    name[++len] = '.';
                    name[++len] = 'l';
                    name[++len] = 'o';
                    name[++len] = 'g';
                    m_file_name += std::string(name);
                }
                struct stat buf;
                if (stat(m_file_name.c_str(), &buf) != 0)
                {
                    printf("CLog::openFile, File is %s Failed\n", m_file_name.c_str());
                    break;
                }
                uint64_t file_size = (uint64_t)buf.st_size;
                if (file_size < (uint64_t)m_file_size)
                {
                    m_rd_fize = file_size;
                    break;
                }
            }
        }
        m_fp = fopen(m_file_name.c_str(), "a+");
        if (!m_fp)
        {
            return -1;
        }
        IncId(m_id);
        return _id1;
    }

    FILE* getFile() { return m_fp; }
    void close() { fclose(m_fp); }
    void rollFile()
    {
        if (m_rd_fize >= m_file_size && m_rotate)
        {
            m_rd_fize = 0;
            close();
            //
            m_file_name = m_file_prefix;
            if (m_is_date > 0)
            {
                char timeString[0x40] = {0};
                time_t unixTime = std::time(NULL);
                std::tm* tm = localtime(&unixTime);
                strftime(timeString, sizeof(timeString), "_%Y%m%d_%H%M%S.log", tm);
                m_file_name += timeString;
                if (m_is_date == 2)
                {
                    std::string old_name = m_file_prefix;
                    old_name += ".log";
                    rename(old_name.c_str(), m_file_name.c_str());
                    m_file_name = old_name;
                }
            }
            else
            {
                ++m_log_num;
                char name[16] = {0};
                name[0] = '_';
                int len = sprintf(name + 1, "%d", m_log_num);
                name[++len] = '.';
                name[++len] = 'l';
                name[++len] = 'o';
                name[++len] = 'g';
                m_file_name += std::string(name);
                if (m_log_num >= m_log_limit)
                {
                    m_log_num = 0;
                    m_file_name = m_file_prefix + ".log";
                }
            }
            m_fp = fopen(m_file_name.c_str(), "w+");
            if (!m_fp)
            {
                printf("CLog::rollFile, File is %s Open Failed\n", m_file_name.c_str());
                return;
            }
        }
    }

    void sync()
    {
        fflush(m_fp);
    }
};

constexpr int32_t ptr_size = sizeof(void*);

class EmptyLock
{
public:
    void lock() {}
    void unlock() {}
};
//
template <typename LOCK>
class CPadLogBuffer
{
    //! 待写出的buff of log
    char* m_buffer = NULL;
    int64_t m_buff_size = 0;
    //! 这里作了假设  不会有连续的可以达到这个数量级的日志数据
    std::atomic<uint64_t> m_wt_pos = { 0 };
    char pad[64];
    std::atomic<uint64_t> m_rd_pos = { 0 };
    char pad0[64];
    std::atomic<uint64_t> m_max_tm = { 0 };
    char* m_format_buf = NULL;
    char pad1[64];
    //! 写出回调
    _GetLog m_get_log;
    //!
    int32_t m_id = 0;
    int32_t m_space_idx = 0;
    //!
    uint64_t wt_pos = 0;
    uint64_t ptr_wt_pos = 0;
    //!
    int32_t m_next = 0;
    //!
    LOCK m_lock;
    //! buf扩容的隔离
    std::mutex m_bf_lk;
public:
    void lock() { m_lock.lock(); }
    void unlock() { m_lock.unlock(); }
public:
    CPadLogBuffer() { m_space_idx = 1; m_next = 1; }
    CPadLogBuffer(int32_t buffSize, _GetLog dumpFun, int id)
    {
        m_buffer = (char*)malloc(sizeof(char) * buffSize);
        memset(m_buffer, 0, buffSize);
        m_buff_size = buffSize;
        m_get_log = dumpFun;
        m_id = id;
        m_space_idx = 1;
        m_next = 1;
    }
    ~CPadLogBuffer()
    {
        free(m_buffer);
        if (m_format_buf)
            free(m_format_buf);
    }
public:
    int32_t id() { return m_id; }
    int allocFormatBuf(int32_t len)
    {
		int length = 0;
        for (; m_space_idx <= m_buff_size / 256; ++m_space_idx)
        {
			length = sizeof(char) * m_space_idx * 256;
            if (len <= length)
            {
                assert(len < m_buff_size);
                m_format_buf = (char*)malloc(length);
                break;
            }
        }
        m_space_idx = 0;
		return length;
    }
public:
    bool shouldWait()
    {
        return m_wt_pos.load(std::memory_order_relaxed) - m_rd_pos.load(std::memory_order_relaxed) > 0 ? false : true;
    }

    int64_t maxTm()
    {
        return m_max_tm.load(std::memory_order_relaxed);
    }

    template<int32_t Num, typename ...Ts>
    void WriteLog(int32_t log_id, int32_t lv, uint32_t tid, int32_t args_len, const char(&Format)[Num], Param_Type* t_params, Ts&&... Params)
    {
        wt_pos = 0;
        int32_t total_len = LogPackSize + args_len;
        int32_t mod = m_buff_size - 1;
        if (total_len > m_buff_size)
        {
            printf("WriteLog: total_size > buff_size!!!\n");
            return;
        }
        int64_t s_t = nanos();
        int64_t c_t = 0;
        do
        {
            wt_pos = m_wt_pos.load(std::memory_order_relaxed);
            //如果可写区域不足
            if (wt_pos - m_rd_pos.load(std::memory_order_acquire) > (int64_t)m_buff_size - total_len)
            {
                ++c_t;
                continue;
            }
            break;
        } while (1);
        //大概在100u左右则扩容 --- 最大8M
        if (c_t >= 250000 && m_buff_size < 8 * 1024 * 1024)
        {
            m_bf_lk.lock();
            int buf_size = m_buff_size;
            m_buff_size *= 2;
            m_buffer = (char*)realloc(m_buffer, sizeof(char) * m_buff_size);
            //挪原跨边界的数据
            uint64_t rd_pos = m_rd_pos.load(std::memory_order_relaxed);
            uint64_t wt_pos_ = wt_pos & mod;
            rd_pos &= mod;
            int len = 0;
            if (wt_pos_ < rd_pos)
            {
                len = buf_size - rd_pos;
                memcpy(m_buffer + m_buff_size - len, m_buffer + buf_size - len, len);
                rd_pos = m_buff_size - len;
            }
            if (wt_pos_ < rd_pos)
            {
                wt_pos_ += m_buff_size;
            }
            m_rd_pos.store(rd_pos);
            m_wt_pos.store(wt_pos_);
            wt_pos = wt_pos_;
            mod = m_buff_size - 1;
            m_bf_lk.unlock();
            printf("Extend log buf, tid:%d, size:%d --->size:%ld\n", tid, buf_size, m_buff_size);
        }
        //写头
        int32_t arg_num = sizeof...(Ts);
        //写format --- format是常量字符串 存指针即可
        uint64_t wt_pos_ = wt_pos & mod;
        int32_t range_len = m_buff_size - wt_pos_;
        if (range_len >= LogPackSize)
        {
            new (m_buffer + wt_pos_)CLogPack(log_id, lv, tid, s_t, arg_num, Format, Num, args_len);
            wt_pos += LogPackSize;
        }
        else
        {
            CLogPack pack(log_id, lv, tid, s_t, arg_num, Format, Num, args_len);
            char* ptr = (char*)&pack;
            for (int i = 0; i < LogPackSize; i += 4)
            {
                m_buffer[wt_pos & mod] = ptr[i];
                m_buffer[(wt_pos + 1) & mod] = ptr[i + 1];
                m_buffer[(wt_pos + 2) & mod] = ptr[i + 2];
                m_buffer[(wt_pos + 3) & mod] = ptr[i + 3];
                wt_pos += 4;
            }
        }
        //写数据
        WriteLog<0>(t_params, std::forward<Ts>(Params)...);

        //提交新位置
        std::atomic_signal_fence(std::memory_order_release);
        m_wt_pos.store(wt_pos, std::memory_order_relaxed);
        m_max_tm.store(s_t, std::memory_order_relaxed);
    }

    template<int index>
    void WriteLog(Param_Type* t_params)
    {
        (void)t_params;
    }

    template<int index, typename T>
    void WriteLog(Param_Type* t_params, T&& param)
    {
        Param_Type& _type = *(t_params + index);
        int32_t arg_size = _type.arg_size;
        int32_t arg_type = _type.arg_type;
        int32_t arg_len = arg_size + 8;
        int32_t mod = m_buff_size - 1;
        ptr_wt_pos = wt_pos & mod;
        int32_t range_len = m_buff_size - ptr_wt_pos;
        //可写区域足够
        if (range_len >= arg_len)
        {
            int32_t* ptr = (int32_t*)(m_buffer + ptr_wt_pos);
            *ptr = arg_type;
            ptr_wt_pos += 4;
            ptr = (int32_t*)(m_buffer + ptr_wt_pos);
            *ptr = arg_size;
            ptr_wt_pos += 4;
            PadConv::CopyStr(std::forward<T>(param), m_buffer + ptr_wt_pos, m_buff_size - 1);
            wt_pos += arg_size + 8;
        }
        else
        {
			char* ptr = (char*)&arg_type;
            m_buffer[wt_pos & mod] = ptr[0];
            m_buffer[(wt_pos + 1) & mod] = ptr[1];
            m_buffer[(wt_pos + 2)  & mod] = ptr[2];
            m_buffer[(wt_pos + 3)  & mod] = ptr[3];
            wt_pos += 4;
			ptr = (char*)&arg_size;
            m_buffer[wt_pos & mod] = ptr[0];
            m_buffer[(wt_pos + 1) & mod] = ptr[1];
            m_buffer[(wt_pos + 2)  & mod] = ptr[2];
            m_buffer[(wt_pos + 3)  & mod] = ptr[3];
            wt_pos += 4;
            PadConv::CopyStr(std::forward<T>(param), m_buffer, arg_size, wt_pos, mod);
        }
    }

    template<int index, typename T, typename ...Ts>
    void WriteLog(Param_Type* t_params, T&& param, Ts&&... params)
    {
        WriteLog<index>(t_params, std::forward<T>(param));
        WriteLog<index + 1>(t_params, std::forward<Ts>(params)...);
    }

    inline int32_t printLogHead(int32_t lv, uint32_t pid, uint32_t tid, int64_t nanos, char* head_string)
    {
        int64_t sec = nanos;
        int64_t cut = 1000000000;
        sec /= cut;
        char timeString[0x30];
#ifndef _WIN32
		time_t unixTime = sec;
		struct tm _tinfo;
		std::tm* tm_ = localtime_r(&unixTime, &_tinfo);
		strftime(timeString, sizeof(timeString), "[%Y-%m-%d %H:%M:%S", tm_);
#else
		time_t unixTime = sec;
		struct tm tm_;
		localtime_s(&tm_, &unixTime);
		strftime(timeString, sizeof(timeString), "[%Y-%m-%d %H:%M:%S", &tm_);
#endif
        int32_t _nanos = nanos - sec * cut;
        return sprintf(head_string, "%s.%09d][PID:%d][TID:%u]%s", timeString, _nanos, pid, tid, LvArr[lv]);
    }

    //写日志数据到文件
    struct _WtData
    {
        const char* m_ptr;
        CLog* m_log;
        uint64_t m_dt_pos;
        int32_t m_len;
        int32_t m_id;
        _WtData() : m_ptr(NULL), m_log(NULL), m_dt_pos(0), m_len(0), m_id(0) {}
        _WtData(const char* ptr, CLog* log, uint64_t pos, int32_t len, int32_t id) : m_ptr(ptr), m_log(log), m_dt_pos(pos), m_len(len), m_id(id) {}
    };
    std::pair<int64_t, _WtData> m_dump_data;

    void updateReadPos(uint64_t pos)
    {
        m_rd_pos.store(pos, std::memory_order_release);
    }

    void updateGo(int32_t next)          //1可以读取下一个   0排序等待中
    {
        m_next = next;
    }

    std::pair<int64_t, _WtData> dumpLog()
    {
        m_bf_lk.lock();
        int32_t mod = m_buff_size - 1;
        uint64_t rd_pos = m_rd_pos.load(std::memory_order_relaxed);
        if (rd_pos >= m_wt_pos.load(std::memory_order_acquire))
        {
            m_bf_lk.unlock();
            return std::pair<int64_t, _WtData>(-1, _WtData());
        }
        int64_t pack_tm = 0;
        CLogPack pack;
        char* ptr = (char*)&pack;
        for (int i = 0; i < LogPackSize; ++i)
        {
            ptr[i] = m_buffer[(rd_pos + i) & mod];
        }
        rd_pos += LogPackSize;
        pack_tm = pack.nanos;
        CLog* log = m_get_log(pack.logid);
        //写头
        char head_string[0x40];
        int32_t write_len = printLogHead(pack.lv, log->m_pid, pack.tid, pack.nanos/*nanos()*/, head_string);
        int32_t buf_len = allocFormatBuf(pack.length + pack.num + write_len);
        //格式化数据
        memcpy(m_format_buf, head_string, write_len);

        int32_t arg_num = pack.arg_num;
        uint64_t data_pos = rd_pos;
        int32_t arg_type = 0;
        int32_t arg_size = 0;
        for (int32_t i = 0; i < pack.num; ++i)
        {
            if (pack.format_ptr[i] == '{' && pack.format_ptr[i + 1] == '}' && arg_num > 0)
            {
                //参数类型和长度
                char* ptr = (char*)&arg_type;
                for (int j = 0; j < 4; ++j)
                {
                    ptr[j] = m_buffer[data_pos & mod];
                    data_pos += 1;
                }
                ptr = (char*)&arg_size;
                for (int j = 0; j < 4; ++j)
                {
                    ptr[j] = m_buffer[data_pos & mod];
                    data_pos += 1;
                }
                ++i;
                //写数据
                CopyData(arg_type, arg_size, buf_len, write_len, data_pos);
                --arg_num;
            }
            else
            {
                m_format_buf[write_len] = pack.format_ptr[i];
                rd_pos += 1;
                write_len += 1;
            }
        }
        //如果参数没解析完 -- 跳过记录区
        while (arg_num > 0)
        {
            char* ptr = (char*)&arg_type;
            data_pos += 4;
            ptr = (char*)&arg_size;
            for (int j = 0; j < 4; ++j)
            {
                ptr[j] = m_buffer[data_pos & mod];
                data_pos += 1;
            }
            data_pos += arg_size;
            --arg_num;
        }
        //结束 换行
        m_format_buf[write_len - 1] = '\n';
        m_dump_data = std::pair<int64_t, _WtData>(pack_tm, _WtData(m_format_buf, log, data_pos, write_len, m_id));
        updateReadPos(data_pos);
        m_format_buf = NULL;
        m_bf_lk.unlock();
        return m_dump_data;
    }

	void extendBuf(int32_t wrt_len, int32_t& buf_len)
	{
		if (wrt_len >= buf_len)
		{
			buf_len += 256;
			m_format_buf = (char*)realloc(m_format_buf, buf_len);
		}
	}
    
    void CopyData(int32_t arg_type, int32_t arg_size, int32_t& buf_len, int32_t& wrt_pos, uint64_t& data_pos)
    {
        int32_t mod = m_buff_size - 1;
        int64_t pos = data_pos & mod;
        switch (arg_type)
        {
        case TypeBool:
        {
            char bytes[4];
            bool val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeInt8:
        {
            char bytes[4];
            int8_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = 1;
            if (val >= 33 && val < 127)
            {
				extendBuf(wrt_pos + 3, buf_len);
                *(m_format_buf + wrt_pos) = '\'';
                *(m_format_buf + wrt_pos + 1) = val;
                *(m_format_buf + wrt_pos + 2) = '\'';
                wrt_pos += 3;
            }
            else
            {
                len = PadConv::MyPrintf(val, bytes);
				extendBuf(wrt_pos + len, buf_len);
                memcpy(m_format_buf + wrt_pos, bytes, len);
                wrt_pos += len;
            }
            data_pos += arg_size;
            break;
        }
        case TypeUint8:
        {
            char bytes[4];
            uint8_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = 1;
            if (val >= 33 && val < 127)
            {
				extendBuf(wrt_pos + 3, buf_len);
                *(m_format_buf + wrt_pos) = '\'';
                *(m_format_buf + wrt_pos + 1) = val;
                *(m_format_buf + wrt_pos + 2) = '\'';
                wrt_pos += 3;
            }
            else
            {
                len = PadConv::MyPrintf(val, bytes);
				extendBuf(wrt_pos + len, buf_len);
                memcpy(m_format_buf + wrt_pos, bytes, len);
                wrt_pos += len;
            }
            data_pos += arg_size;
            break;
        }
        case TypeInt16:
        {
            char bytes[24];
            int16_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%d", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeUint16:
        {
            char bytes[24];
            uint16_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%u", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeInt32:
        {
            char bytes[24];
            int32_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%d", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeUint32:
        {
            char bytes[24];
            uint32_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%u", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeInt64:
        {
            char bytes[32];
            int64_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeUint64:
        {
            char bytes[32];
            uint64_t val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeLLong:
        {
            char bytes[32];
            long long val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%lld", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeULLong:
        {
            char bytes[32];
            unsigned long long val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            //            int len = sprintf(bytes, "%llu", val);
            int len = PadConv::MyPrintf(val, bytes);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeFloat:
        {
            char bytes[32];
            float val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = sprintf(bytes, "%0.6f", val);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeDouble:
        {
            char bytes[48];
            double val = 0;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = sprintf(bytes, "%.8lf", val);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypePoint:
        {
            char bytes[32] = { 0 };
            void* val = NULL;
            char* ptr = (char*)&val;
            for (int i = 0; i < arg_size; ++i)
            {
                ptr[i] = m_buffer[(data_pos + i) & mod];
            }
            int len = sprintf(bytes, "%p", val);
			extendBuf(wrt_pos + len, buf_len);
            memcpy(m_format_buf + wrt_pos, bytes, len);
            wrt_pos += len;
            data_pos += arg_size;
            break;
        }
        case TypeChars:
        case TypeConstChars:
        case TypeString:
        {
			extendBuf(wrt_pos + arg_size, buf_len);
            if (m_buff_size - pos >= arg_size)
            {
                memcpy(m_format_buf + wrt_pos, m_buffer + (data_pos & mod), arg_size);
            }
            else
            {
                for (int i = 0; i < arg_size; ++i)
                {
                    m_format_buf[wrt_pos + i] = m_buffer[(data_pos + i) & mod];
                }
            }
            wrt_pos += arg_size;
            data_pos += arg_size;
            break;
        }
        case TypeArrChars:
        {
            char _char = 0;
            int _size = 0;
			extendBuf(wrt_pos + arg_size, buf_len);
            for (int i = 0; i < arg_size; ++i)
            {
                _char = m_buffer[(data_pos + i) & mod];
                if (_char == '\0')      //这种当作字符串处理
                    break;
                m_format_buf[wrt_pos + i] = _char;
                ++_size;
            }
            wrt_pos += _size;
            data_pos += arg_size;
            break;
        }
        default:
            break;
        }
    }

};

typedef std::function<void()> _VoidFun;
//日志poller
template <typename LOCK>
class CPadLogPoller
{
    //!
    int32_t m_is_run = 0;
    //! 每个线程分配的待写出buf
    CPadLogBuffer<LOCK>* m_log_thread_buf[ThrdCnt];
    std::atomic<int> m_buf_cnt;
    std::atomic<int> m_real_buf_cnt;
    //!
    std::thread m_log_runner;
    std::mutex m_lock;
    std::condition_variable m_wait;
    //!
    _VoidFun m_sync;
public:
    CPadLogPoller(_VoidFun fun) : m_sync(fun)
    {
        m_is_run = 1;
        memset(m_log_thread_buf, 0, sizeof(m_log_thread_buf));
        m_buf_cnt.store(0);
        m_real_buf_cnt.store(0);
        m_log_runner = std::thread(&CPadLogPoller::logPoller, this);
    }

    ~CPadLogPoller()
    {
        m_is_run = 0;
        m_log_runner.join();
        for (int i = 0; i < m_real_buf_cnt.load(); ++i)
        {
            delete m_log_thread_buf[i];
        }
    }

    void addBuffer(CPadLogBuffer<LOCK>** buff, int bufsize, _GetLog fun)
    {
        CPadLogBuffer<LOCK>* pbuf = NULL;
        int buf_id = m_buf_cnt.fetch_add(1, std::memory_order_release);
        if (buf_id < ThrdCnt)
        {
            m_real_buf_cnt.fetch_add(1);
            pbuf = new CPadLogBuffer<LOCK>(bufsize, fun, buf_id);
            *buff = pbuf;
            m_log_thread_buf[buf_id] = pbuf;
            std::atomic_thread_fence(std::memory_order_release);
        }
        else
        {
            do
            {
                std::atomic_thread_fence(std::memory_order_acquire);
                pbuf = m_log_thread_buf[buf_id % ThrdCnt];
            } while (!pbuf);
            *buff = pbuf;
        }
    }

    //驱动线程
    void logPoller()
    {
        typedef std::pair<int64_t, int> BUF_TIMESTAMP;
        int64_t t1 = nanos();
        int64_t t2 = 0;
        int64_t min_time = 0;
        int64_t max_time = 0;
        std::multimap<BUF_TIMESTAMP, typename CPadLogBuffer<LOCK>::_WtData> sort_vec;
        while (m_is_run)
        {
            t2 = nanos();
            if (t2 - t1 >= 10 * 1000 * 1000)
            {
                t1 = t2;
                m_sync();
            }
            min_time = 0x7FFFFFFFFFFFFFFF;
            max_time = 0;
            for (int i = 0; i < m_real_buf_cnt.load(); ++i)
            {
                CPadLogBuffer<LOCK>* buf_ptr = m_log_thread_buf[i];
                if (!buf_ptr)
                    continue;
                int64_t tm_ = buf_ptr->maxTm();
                if (tm_ > max_time)
                {
                    max_time = tm_;
                }
            }
            for (int i = 0; i < m_real_buf_cnt.load(); ++i)
            {
                CPadLogBuffer<LOCK>* buf_ptr = m_log_thread_buf[i];
                if (!buf_ptr)
                    continue;
                do
                {
                    auto iter = buf_ptr->dumpLog();
                    if (iter.first < 0)
                    {
                        break;
                    }
                    typename CPadLogBuffer<LOCK>::_WtData data;
                    data.m_ptr = iter.second.m_ptr;
                    data.m_id = iter.second.m_id;
                    data.m_len = iter.second.m_len;
                    data.m_log = iter.second.m_log;
                    data.m_dt_pos = iter.second.m_dt_pos;
                    auto pair_ = std::make_pair(iter.first, iter.second.m_id);
                    sort_vec.emplace(pair_, data);
                    if (min_time > iter.first)
                    {
                        min_time = iter.first;
                    }
                    if (iter.first > max_time)
                    {
                        break;
                    }
                } while(1);
            }
            if (!sort_vec.empty())
            {
                auto iter = sort_vec.begin();
                for (; iter != sort_vec.end();)
                {
                    if (iter->first.first > max_time)
                    {
                        break;
                    }
                    CLog* log = iter->second.m_log;
                    const char* ptr = iter->second.m_ptr;
                    int32_t len = iter->second.m_len;
                    FILE* fp = log->getFile();
                    assert(fp);
                    fwrite(ptr, len, 1, fp);
                    log->m_rd_fize += len;
                    //                    delete[] iter->second.m_ptr;
                    free((void*)iter->second.m_ptr);
                    iter = sort_vec.erase(iter);
                    //判断是否滚动文件
                    log->rollFile();
                }
            }
            if (!sort_vec.empty())
            {
                continue;
            }
            std::unique_lock<std::mutex> lock(m_lock);
            m_wait.wait_for(lock, std::chrono::microseconds(1));
        }
    }

    bool shouldWait()
    {
        if (m_buf_cnt.load() < 1)
        {
            return true;
        }
        bool ret = false;
        for (int i = 0; i < m_buf_cnt.load(); ++i)
        {
            CPadLogBuffer<LOCK>* buf_ptr = m_log_thread_buf[i];
            if (!buf_ptr)
                continue;
            ret = buf_ptr->shouldWait();
            if (ret)
            {
                break;
            }
        }
        return ret;
    }
};

}
#endif